package com.have.blog.xo.service.admin.impl;

import com.github.pagehelper.PageHelper;
import com.have.blog.base.constant.BlogConstant;
import com.have.blog.base.enums.BlogOriginal;
import com.have.blog.base.enums.BlogPublishStatus;
import com.have.blog.base.enums.BlogStatus;
import com.have.blog.base.holder.RequestHolder;
import com.have.blog.commons.config.jwt.Audience;
import com.have.blog.model.api.CommonPage;
import com.have.blog.model.constant.SQLConstant;
import com.have.blog.model.mapper.TAdminMapper;
import com.have.blog.model.mapper.TBlogMapper;
import com.have.blog.model.mapper.TBlogSortMapper;
import com.have.blog.model.mapper.TTagMapper;
import com.have.blog.model.models.*;
import com.have.blog.utils.DateUtils;
import com.have.blog.utils.MyStringUtils;
import com.have.blog.utils.ResultUtils;
import com.have.blog.xo.constant.MessageConstant;
import com.have.blog.xo.constant.SysConstant;
import com.have.blog.xo.dao.admin.AdminBlogDao;
import com.have.blog.xo.service.admin.AdminBlogService;
import com.have.blog.xo.service.admin.SystemParamService;
import com.have.blog.xo.service.cache.AdminBlogCacheService;
import com.have.blog.xo.vo.AdminBlogVo;
import com.have.haveblog.security.utils.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@SuppressWarnings("all")
public class AdminBlogServiceImpl implements AdminBlogService {
    @Autowired
    private TBlogMapper blogMapper;
    @Autowired
    private AdminBlogDao blogDao;
    @Autowired
    private TTagMapper tagMapper;
    @Autowired
    private TBlogSortMapper blogSortMapper;
    @Autowired
    private SystemParamService systemParamService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private Audience audience;
    @Autowired
    private TAdminMapper adminMapper;
    @Autowired
    private AdminBlogCacheService blogCacheService;

    @Override
    public Long getBlogCount(Integer status) {
        TBlogExample example = new TBlogExample();
        TBlogExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo(status);
        criteria.andIsPublishEqualTo(BlogPublishStatus.PUBLISH.getStatus());
        Long count = blogMapper.countByExample(example);
        return count;
    }

    @Override
    public String getBlogCountByTag() {
        List<Map<String, Object>> resultList = blogCacheService.getBlogCountByTag();
        if (!CollectionUtils.isEmpty(resultList)) {
            return ResultUtils.result(SysConstant.SUCCESS, resultList);
        }
        // 获取标签和归属于此标签的文章总数
        List<Map<String, Object>> blogCountByTag = blogDao.getBlogCountByTag();
        HashMap<String, Integer> tagMap = new HashMap<>();
        for (Map<String, Object> item : blogCountByTag) {
            String tagUid = String.valueOf(item.get(SQLConstant.TAG_UID));
            Number num = (Number) item.get(SysConstant.COUNT);
            Integer count = num.intValue();
            if (tagUid.length() == 32) { // 单标签
                tagMap.put(tagUid, tagMap.getOrDefault(tagUid, 0) + count);
            } else { // 多标签
                if (!StringUtils.isEmpty(tagUid)) {
                    List<String> tagUidList = MyStringUtils.changeStringToStringList(tagUid, ",");
                    for (String uid : tagUidList) {
                        tagMap.put(tagUid, tagMap.getOrDefault(tagUid, 0) + count);
                    }
                }
            }
        }

        Set<String> tagUidSet = tagMap.keySet();
        TTagExample example = new TTagExample();
        TTagExample.Criteria criteria = example.createCriteria();
        criteria.andUidIn(new ArrayList<>(tagUidSet));
        List<TTag> tagList = tagMapper.selectByExample(example);

        HashMap<String, String> tagEntityMap = new HashMap<>();
        for (TTag tag : tagList) {
            if (!StringUtils.isEmpty(tag.getContent())) {
                tagEntityMap.put(tag.getUid(), tag.getContent());
            }
        }

        resultList = new ArrayList<>();
        for (Map.Entry<String, Integer> entry : tagMap.entrySet()) {
            String tagUid = entry.getKey();
            if (tagEntityMap.get(tagUid) != null) {
                String tagName = tagEntityMap.get(tagUid);
                Integer count = entry.getValue();
                HashMap<String, Object> itemResultMap = new HashMap<>();
                itemResultMap.put(SysConstant.TAG_UID, tagUid);
                itemResultMap.put("name", tagName);
                itemResultMap.put("value", count);
                resultList.add(itemResultMap);
            }
        }

        if (!CollectionUtils.isEmpty(resultList)) {
            blogCacheService.saveBlogCountByTag(resultList, 2, TimeUnit.HOURS);
        }
        return ResultUtils.result(SysConstant.SUCCESS, resultList);
    }

    @Override
    public String getBlogCountByCategory() {

        List<Map<String, Object>> resultList = (List<Map<String, Object>>) blogCacheService.getBlogCountByCategory();
        if (!CollectionUtils.isEmpty(resultList)) {
            return ResultUtils.result(SysConstant.SUCCESS, resultList);
        }

        List<Map<String, Object>> blogCategoryCountList = blogDao.getBlogCountByCategory();
        HashMap<String, Integer> blogCategoryUidCountMap = new HashMap<>();
        for (Map<String, Object> item : blogCategoryCountList) {
            String categoryUid = String.valueOf(item.get("category_uid"));
            Number num = (Number) item.get(SysConstant.COUNT);
            Integer count = 0;
            if (num != null) {
                count = num.intValue();
            }
            blogCategoryUidCountMap.put(categoryUid, count);

        }

        Set<String> categoryUidSet = blogCategoryUidCountMap.keySet();
        TBlogSortExample example = new TBlogSortExample();
        example.createCriteria().andUidIn(new ArrayList<>(categoryUidSet));
        List<TBlogSort> blogCategoryList = blogSortMapper.selectByExample(example);

        HashMap<String, String> blogCategoryEntityMap = new HashMap<>();
        for (TBlogSort item : blogCategoryList) {
            if (!StringUtils.isEmpty(item.getSortName())) {
                blogCategoryEntityMap.put(item.getUid(), item.getSortName());
            }
        }

        resultList = new ArrayList<>();
        for (Map.Entry<String, Integer> entry : blogCategoryUidCountMap.entrySet()) {

            String blogSortUid = entry.getKey();

            if (blogCategoryEntityMap.get(blogSortUid) != null) {
                String blogSortName = blogCategoryEntityMap.get(blogSortUid);
                Integer count = entry.getValue();
                Map<String, Object> itemResultMap = new HashMap<>();
                itemResultMap.put("blogSortUid", blogSortUid);
                itemResultMap.put("bane", blogSortName);
                itemResultMap.put("value", count);
                resultList.add(itemResultMap);
            }
        }

        blogCacheService.saveBlogCountByCategory(resultList, 2, TimeUnit.HOURS);
        return ResultUtils.result(SysConstant.SUCCESS, resultList);
    }

    @Override
    public String getBlogContributeCount() {

        Map<String, Object> resultMap = (Map<String, Object>) blogCacheService.getBlogContributeCount();
        if (!CollectionUtils.isEmpty(resultMap)) {
            return ResultUtils.result(SysConstant.SUCCESS, resultMap);
        }
        // 获取今天结束时间
        String endTime = DateUtils.getNowTime();
        // 获取365天前的日期
        Date temp = DateUtils.getDate(endTime, -365);
        String startTime = DateUtils.dateTimeToStr(temp);

        List<Map<String, Object>> blogContributeMap = blogDao.getBlogContributeCount(startTime, endTime);
        List<String> dateList = DateUtils.getDayBetweenDates(startTime, endTime);
        Map<String, Object> dateMap = new HashMap<>();
        for (Map<String, Object> itemMap : blogContributeMap) {
            dateMap.put(itemMap.get("DATE").toString(), itemMap.get("COUNT"));
        }

        List<List<Object>> resultList = new ArrayList<>();
        for (String item : dateList) {
            Integer count = 0;
            if (dateMap.get(item) != null) {
                count = Integer.valueOf(dateMap.get(item).toString());
            }
            List<Object> objectList = new ArrayList<>();
            objectList.add(item);
            objectList.add(count);
            resultList.add(objectList);
        }


        resultMap = new HashMap<>(BlogConstant.NUM_TWO);
        List<String> contributeDateList = new ArrayList<>();
        contributeDateList.add(startTime);
        contributeDateList.add(endTime);
        resultMap.put("contributeDate", contributeDateList);
        resultMap.put("blogContributeCount", resultList);

        blogCacheService.saveBlogContributeCount(resultMap, 2, TimeUnit.HOURS);
        return ResultUtils.result(SysConstant.SUCCESS, resultMap);
    }

    @Override
    public String getList(AdminBlogVo blogVO) {
        PageHelper.startPage(blogVO.getCurrentPage(), blogVO.getPageSize());

        TBlogExample example = new TBlogExample();
        TBlogExample.Criteria criteria = example.createCriteria();
        if (!StringUtils.isEmpty(blogVO.getKeyword()) && !StringUtils.isEmpty(blogVO.getKeyword().trim())) {
            criteria.andTitleLike("%" + blogVO.getKeyword() + "%");
        }
        if (!StringUtils.isEmpty(blogVO.getUid())) {
            criteria.andUidLike("%" + blogVO.getUid() + "%");
        }
        if (!StringUtils.isEmpty(blogVO.getBlogSortUid())) {
            criteria.andBlogSortUidLike("%" + blogVO.getBlogSortUid() + "%");
        }
        if (!StringUtils.isEmpty(blogVO.getLevel())) {
            criteria.andLevelEqualTo(blogVO.getLevel());
        }
        if (!StringUtils.isEmpty(blogVO.getIsPublish())) {
            criteria.andIsPublishEqualTo(blogVO.getIsPublish());
        }
        if (!StringUtils.isEmpty(blogVO.getIsOriginal())) {
            criteria.andIsOriginalEqualTo(blogVO.getIsOriginal());
        }
        if(!StringUtils.isEmpty(blogVO.getType())) {
            criteria.andTypeEqualTo(blogVO.getType());
        }
        criteria.andStatusEqualTo(BlogStatus.ENABLE.getStatus());

        if (!StringUtils.isEmpty(blogVO.getOrderByAscColumn())) {
            String column = MyStringUtils.underLine(new StringBuffer(blogVO.getOrderByAscColumn())).toString();
            example.setOrderByClause(column + " asc");
        } else if(!StringUtils.isEmpty(blogVO.getOrderByDescColumn())) {
            // 将驼峰转换成下划线
            String column = MyStringUtils.underLine(new StringBuffer(blogVO.getOrderByDescColumn())).toString();
             example.setOrderByClause(column + " desc");
        } else {
            if (blogVO.getUseSort() == 0) {
                example.setOrderByClause("create_time desc");
            } else {
                example.setOrderByClause("sort desc");
            }
        }

        List<TBlog> blogList = blogMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(blogList)) {
            return ResultUtils.successWithData(new ArrayList<TBlog>());
        }

        StringBuffer sbf = new StringBuffer();
        List<String> sortUids = new ArrayList<>();
        List<String> tagUids = new ArrayList<>();
        blogList.forEach(item -> {
            if (!StringUtils.isEmpty(item.getFileUid())) {
                sbf.append(item.getFileUid() + SysConstant.FILE_SEGMENTATION);
            }
            if (!StringUtils.isEmpty(item.getBlogSortUid())) {
                sortUids.add(item.getBlogSortUid());
            }
            if (!StringUtils.isEmpty(item.getTagUid())) {
                List<String> tempList = MyStringUtils.changeStringToStringList(item.getTagUid(), SysConstant.FILE_SEGMENTATION);
                for (String uid : tempList) {
                    tagUids.add(uid);
                }
            }
        });
        // TODO 图片相关功能待完成


        List<TBlogSort> sortList = new ArrayList<>();
        List<TTag> tagList = new ArrayList<>();
        if (sortUids.size() > 0) {
            TBlogSortExample blogSortExample = new TBlogSortExample();
            blogSortExample.createCriteria()
                    .andUidIn(sortUids);
            sortList = blogSortMapper.selectByExample(blogSortExample);
        }
        if (tagList.size() > 0) {
            TTagExample tagExample = new TTagExample();
            tagExample.createCriteria()
                    .andUidIn(tagUids);
            tagList = tagMapper.selectByExample(tagExample);
        }

        Map<String, String> picMap = new HashMap<>();
        Map<String, TTag> tagMap = new HashMap<>();
        Map<String, TBlogSort> blogSortMap = new HashMap<>();

        sortList.forEach(item -> {
            blogSortMap.put(item.getUid(), item);
        });
        tagList.forEach(item -> {
            tagMap.put(item.getUid(), item);
        });

        for (TBlog blog : blogList) {
            if (!StringUtils.isEmpty(blog.getBlogSortUid())) {
                blog.setBlogSort(blogSortMap.get(blog.getBlogSortUid()));
            }
            if (!StringUtils.isEmpty(blog.getTagUid())) {
                List<String> tempTagUidList = MyStringUtils.changeStringToStringList(blog.getTagUid(), SysConstant.FILE_SEGMENTATION);
                List<TTag> tempTagList = new ArrayList<TTag>();
                for (String tagUid : tempTagUidList) {
                    tempTagList.add(tagMap.get(tagUid));
                }
                blog.setTagList(tempTagList);
            }

            // TODO 获取图片
        }
        return ResultUtils.successWithData(CommonPage.restPage(blogList));
    }


    @Override
    public String add(AdminBlogVo blogVO) {
        TBlogExample example = new TBlogExample();
        TBlogExample.Criteria criteria = example.createCriteria();
        criteria.andLevelEqualTo(blogVO.getLevel())
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus());
        long count = blogMapper.countByExample(example);
        String verdictResult = addVerdict(count + 1, blogVO.getLevel());
        if (MyStringUtils.isNotBlank(verdictResult)) {
            return verdictResult;
        }
        TBlog blog = new TBlog();
        String projectName = systemParamService.getSystemParamValueByKey(SysConstant.PROJECT_NAME_);
        if (BlogOriginal.ORIGINAL.equals(blogVO.getIsOriginal())) {
            TAdmin admin = getAdmin();
            if (admin != null) {
                if (!StringUtils.isEmpty(admin.getNickName())) {
                    blog.setAuthor(admin.getNickName());
                } else {
                    blog.setAuthor(admin.getUserName());
                }
                blog.setAdminUid(admin.getUid());
            }
            blog.setArticlesPart(projectName);
        } else {
            blog.setArticlesPart(blogVO.getAuthor());
            blog.setArticlesPart(blogVO.getArticlesPart());
        }
        // TODO 修改代码
        blog.setSort(0);
        blog.setArticleSource(0);
        blog.setStartComment(1);

        blog.setUid(MyStringUtils.getUUID());
        blog.setTitle(blogVO.getTitle());
        blog.setSummary(blogVO.getSummary());
        blog.setContent(blogVO.getContent());
        blog.setTagUid(blogVO.getTagUid());
        blog.setBlogSortUid(blogVO.getBlogSortUid());
        blog.setFileUid(blogVO.getFileUid());
        blog.setLevel(blogVO.getLevel());
        blog.setIsOriginal(blogVO.getIsOriginal());
        blog.setIsPublish(blogVO.getIsPublish());
        blog.setType(blogVO.getType());
        blog.setOutsideLink(blogVO.getOutsideLink());
        blog.setStatus(BlogStatus.ENABLE.getStatus());
        blog.setOpenComment(blogVO.getOpenComment());
        blog.setUpdateTime(new Date());
        blog.setCreateTime(new Date());
        blogMapper.insert(blog);

        // TODO 保存成功后需要发送消息到solr和redis
        return ResultUtils.successWithData(MessageConstant.INSERT_SUCCESS);
    }

    @Override
    public String edit(AdminBlogVo blogVo) {
        TBlogExample example = new TBlogExample();
        example.createCriteria()
                .andUidEqualTo(blogVo.getUid());
        List<TBlog> blogs = blogMapper.selectByExample(example);
        TBlog blog = blogs.get(0);

        example.clear();
        example.createCriteria()
                .andLevelEqualTo(blogVo.getLevel())
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus());
        long count = blogMapper.countByExample(example);

        if (blog != null) {
            if (!blog.getLevel().equals(blogVo.getLevel())) {
                count += 1;
            }
        }

        String verdictResult = addVerdict(count, blogVo.getLevel());
        if (MyStringUtils.isNotBlank(verdictResult)) {
            return verdictResult;
        }

        TAdmin admin = getAdmin();
        blog.setAdminUid(admin.getUid());
        if (BlogOriginal.ORIGINAL.equals(blogVo.getIsOriginal())) {
            if (!StringUtils.isEmpty(admin.getNickName())) {
                blog.setAuthor(admin.getNickName());
            } else {
                blog.setAuthor(admin.getUserName());
            }
            String projectName = systemParamService.getSystemParamValueByKey(SysConstant.PROJECT_NAME_);
            blog.setArticlesPart(projectName);
        } else {
            blog.setArticlesPart(blogVo.getAuthor());
            blog.setArticlesPart(blogVo.getArticlesPart());
        }

        blog.setTitle(blogVo.getTitle());
        blog.setSummary(blogVo.getSummary());
        blog.setContent(blogVo.getContent());
        blog.setTagUid(blogVo.getTagUid());
        blog.setBlogSortUid(blogVo.getBlogSortUid());
        blog.setFileUid(blogVo.getFileUid());
        blog.setLevel(blogVo.getLevel());
        blog.setIsOriginal(blogVo.getIsOriginal());
        blog.setIsPublish(blogVo.getIsPublish());
        blog.setType(blogVo.getType());
        blog.setOutsideLink(blogVo.getOutsideLink());
        blog.setStatus(BlogStatus.ENABLE.getStatus());
        blog.setOpenComment(blogVo.getOpenComment());
        blog.setCreateTime(new Date());
        blogMapper.updateByPrimaryKeySelective(blog);

        // TODO 保存成功后需要发送消息到solr和redis
        return ResultUtils.successWithData(MessageConstant.UPDATE_SUCCESS);

    }

    @Override
    public String delete(AdminBlogVo blogVO) {
        TBlogExample example = new TBlogExample();
        example.createCriteria()
                .andUidEqualTo(blogVO.getUid());
        List<TBlog> blogs = blogMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(blogs)) {
            return ResultUtils.errorWithMessage(MessageConstant.PARAM_INCORRECT);
        }
        TBlog blog = blogs.get(0);
        blog.setStatus(BlogStatus.DISABLE.getStatus());
        int count = blogMapper.updateByPrimaryKeySelective(blog);
        // TODO 更新成功后需要发送消息到solr和redis，同时从专题管理Item中移除该博客，删除博客评论

        return ResultUtils.successWithMessage(MessageConstant.DELETE_SUCCESS);
    }


    @Override
    public String deleteBatchBlog(List<AdminBlogVo> blogVoList) {
        if (CollectionUtils.isEmpty(blogVoList)) {
            return ResultUtils.errorWithMessage(MessageConstant.PARAM_INCORRECT);
        }
        TBlogExample example = new TBlogExample();
        List<String> uidList = new ArrayList<>();
        blogVoList.forEach(item -> {
            uidList.add(item.getUid());
        });
        example.createCriteria()
                .andUidIn(uidList)
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus());
        TBlog blog = new TBlog();
        blog.setStatus(BlogStatus.DISABLE.getStatus());
        blogMapper.updateByExampleSelective(blog, example);

        // TODO 保存成功后，需要发送消息到solar和redis
        return ResultUtils.successWithMessage(MessageConstant.DELETE_SUCCESS);
    }

    /**
     * 添加时校验
     *
     * @param count
     * @param level
     * @return
     */
    private String addVerdict(Long count, Integer level) {

        //添加的时候进行判断
        switch (level) {
            case 1: {
                Long blogFirstCount = Long.valueOf(systemParamService.getSystemParamValueByKey(SysConstant.BLOG_FIRST_COUNT));
                if (count > blogFirstCount) {
                    return ResultUtils.errorWithMessage("一级推荐不能超过" + blogFirstCount + "个");
                }
            }
            break;

            case 2: {
                Long blogSecondCount = Long.valueOf(systemParamService.getSystemParamValueByKey(SysConstant.BLOG_SECOND_COUNT));
                if (count > blogSecondCount) {
                    return ResultUtils.errorWithMessage("二级推荐不能超过" + blogSecondCount + "个");
                }
            }
            break;

            case 3: {
                Long blogThirdCount = Long.valueOf(systemParamService.getSystemParamValueByKey(SysConstant.BLOG_THIRD_COUNT));
                if (count > blogThirdCount) {
                    return ResultUtils.errorWithMessage("三级推荐不能超过" + blogThirdCount + "个");
                }
            }
            break;

            case 4: {
                Long blogFourthCount = Long.valueOf(systemParamService.getSystemParamValueByKey(SysConstant.BLOG_FOURTH_COUNT));
                if (count > blogFourthCount) {
                    return ResultUtils.errorWithMessage("四级推荐不能超过" + blogFourthCount + "个");
                }
            }
            break;
            default: {

            }
        }
        return null;
    }

    private TAdmin getAdmin() {
        HttpServletRequest request = RequestHolder.getRequest();
        String jwtToken = (String) request.getAttribute(SysConstant.TOKEN);
        String adminUid = jwtTokenUtil.getAdminUid(jwtToken, audience.getBase64Secret());
        TAdmin admin = adminMapper.selectByPrimaryKey(adminUid);
        return admin;
    }
}
